/**
 * 设计模式 为了批量创建对象 为了继承
 * 1.工厂模式 
 * 2.构造函数模式
 * 3.原型模式
 * 4.组合模式
 */
// var obj = {
//   name:'zhangsan',
//   age:12,
//   gender:'male',
// }
// var obj1 = {
//   name:"lisi",
//   age:16,
//   gender:'female'
// }
// var obj2 = new Object();
// obj2.name = 'xxx';
// obj2.age = 12;
// var obj3 = new Object();
// obj3.xxx = 'xxx';


/**
 * 工厂模式
 * 优点：可以批量创建对象 
 * 缺点：无法区分种类，所有工厂函数创建对象实例都是Object实例 方法冗余
 */
// 创建一个工厂函数 返回一个对象 造人对象工厂模式
// var say = function(){
//   console.log(this.name);
// }
// function Person(name,age,gender){
//   return {
//     name:name,
//     age:age,
//     gender:gender,
//     sayName:say,
//   }
// }
// var p1 = Person('张三',12,'male');
// var p2 = Person('李四',15,'female');
// console.log(p1,p2);
// p1.sayName();
// p2.sayName();
// console.log(p1.sayName === p2.sayName);
// function Animal(){
//   return {
//     sayName:say
//   }
// }
// var a1 = Animal();


/**
 * 构造函数模式 
 * 优点：可以批量创建对象，可以区分种类Person{} Animal{} 
 * 缺点：方法冗余 
 */
// var sayName = function(){
//   console.log(this.name);
// };
// function Person(name,age,gender){
//   /**
//    * new关键字做了什么事情
//    * 1.创建一个构造函数实例 Person{} p1 p2
//    * 2.将this指向构造函数实例 p1 p2
//    * 3.执行函数体内得代码 
//    * 4.返回实例 p1 p2
//    */
//   this.name = name;
//   this.age = age;
//   this.gender = gender;
//   this.sayName = sayName;
// }
// var p1 = new Person('terry',18,'male');
// var p2 = new Person('larry',28,'female');
// console.log(p1,p2);

// function Animal(){}
// var a1 = new Animal();
// console.log(a1);

/**
 * 3.原型模式（不单独使用)
 * 构造函数什么事情都不做 
 * 将所有实例属性和方法全部放在原型对象中 
 * 优点：可以批量创建对象 解决方法冗余问题
 * 缺点：创建所有实例都一样 
 */
// function Person(){}
// Person.prototype.name = 'ronda';
// Person.prototype.age = 18;
// Person.prototype.gender ='female';
// Person.prototype.sayName = function(){
//   console.log(this.name);
// };
// Person.prototype.friends = [];
// var p1 = new Person();
// var p2 = new Person();
// console.log(p1,p2,p1.name,p2.name,p1.sayName === p2.sayName);
// p1.sayName();
// p2.sayName();
// p1.friends.push('tom');
// console.log(p1.friends,p2.friends);


/**
 * 组合模式 
 *  原型模式 + 构造函数模式 
 *  将实例公共属性和公共方法放在原型对象中
 *  将实例私有属性和私有方法放在构造函数中
 */
function Person(name, age, gender, weight) {
    // 将实例私有属性和方法放在构造函数中
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.weight = function () {
        console.log(weight);
    }
}
// 将实例公共属性和公共方法放在原型对象中 
Person.prototype.type = 'Person实例';
Person.prototype.sayName = function () {
    console.log(this.name);
}
var p1 = new Person('terry', 18, 'male', '40kg');
var p2 = new Person('larry', 38, 'female', '60kg');
console.log(p1, p2);
p1.weight();
p2.weight();
console.log(p1.weight === p2.weight);
console.log(p1.type, p2.type, p1.type === p2.type);
p1.sayName();
p2.sayName();
console.log(p1.sayName === p2.sayName);

// instanceof 检测是否是构造函数实例 是否在原型链上 

console.log(p1 instanceof Person);
console.log(p1 instanceof Object);
console.log(p1 instanceof Array);
console.log(Person instanceof Object);
